package uk.ac.aber.paws.client.state;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.Level;

import uk.ac.aber.paws.client.constants.Constants;
import uk.ac.aber.paws.client.core.Initiator;
import uk.ac.aber.paws.client.core.PAWSClient;
import uk.ac.aber.paws.client.net.DNSLookup;
import uk.ac.aber.paws.client.util.MACAddressFinder;

/**
 * @author Rob Johnson, Aberystwyth University
 * @email rob.johnson@aber.ac.uk
 * @date 16th August 2011
 * 
 * ComputerInfo.java
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

public class ComputerInfo {

	/**
	 * The computer name of this client as depicted by the computername environment var
	 */
	private String computerName = null;
		
	/**
	 * Stores the environment variable BUILD stored on the system. Good for keeping track of the
	 * operating system build version that the user is using
	 */
	private String osBuild = null;
	
	/**
	 * Stores the current version of the runtime virtual admin client.
	 */
	private String pawsVersion = null;
	
	private String domainName = null;
	
	/**
	 * This value is read from the BIOS to store the hard encoded serial number.
	 */
	private String serialNumber = null;
	
	private String macAddress = null;
	
	private String ipAddress = null;
	
	private String operatingSystem = null;
	
	public ComputerInfo() {
		
		initialiseEnvVarParams();
			
		initialiseNetworkParams();
		
		initialiseBIOSParams();
		
		initialiseGenericParams();
	}
	
	public boolean initSuccessful() {
		
		if (computerName == null) {
			return false;
		}
		
		return true;
	}

	private void initialiseEnvVarParams() {
		
		operatingSystem = System.getProperty("os.name").toUpperCase();
		
		Initiator.LOG_FILE.log(Level.INFO,"OS detected as: "+operatingSystem);
		
		if (System.getenv(PAWSClient.getConfig().getProperty("app.os.config.domain")) != null) {
			domainName = System.getenv(PAWSClient.getConfig().getProperty("app.os.config.domain"));
		}
		else {
			domainName = "unknown";
		}
		
		Initiator.LOG_FILE.log(Level.INFO,"Registered to Domain: "+domainName);
		
		if (System.getenv(PAWSClient.getConfig().getProperty("app.os.config.build")) != null) {
			osBuild = System.getenv(PAWSClient.getConfig().getProperty("app.os.config.build"));
		}
		else {
			osBuild = "unknown";
		}
		
		Initiator.LOG_FILE.log(Level.INFO,"Machine build version: "+osBuild);
	
	}
	private void initialiseGenericParams() {
		
		pawsVersion = Constants.VERSION;
		Initiator.LOG_FILE.log(Level.INFO,"PAWS Client version: "+pawsVersion);
		
	}
	
	private void initialiseBIOSParams() {
		
		// get the BIOS serial number using WMI - this may not be available on all systems
		new Thread(new Runnable() {
			public void run() {
				try {
					//SERIAL_NUM = WMIOperations.getSerialNumber();
					serialNumber = "DISABLED";
					Initiator.LOG_FILE.log(Level.INFO,"BIOS serial number of this computer: "+serialNumber);
				} 
				catch (Exception e) {
					e.printStackTrace();
				}
	                    
			}
		}).start();
	}
	
	private void initialiseNetworkParams() {
		
		try {
			
			// Perform a DNS lookup by using the IP address of the main adapter, formulates the
			// hosts's fully qualified domain name - this identity is important as used in all
			// logging operations and identity etc
			DNSLookup dns = new DNSLookup();
			
			if (operatingSystem.equals(Constants.OS_FLAG_LINUX)) {
				
				computerName = InetAddress.getLocalHost().getCanonicalHostName().toUpperCase();
			}
			else if (operatingSystem.equals(Constants.OS_FLAG_MAC)) {
				
				computerName = InetAddress.getLocalHost().getCanonicalHostName().toUpperCase();
			}
			else {
				// get a list of all the NICs available on this system
				InetAddress[] allNICs = InetAddress.getAllByName(InetAddress.getLocalHost().getCanonicalHostName());
				
				if (allNICs != null) {
					
					String ipList = "";
					
					// build up a comma separated list of IP address for all NICs
				    for (int i=0;i<allNICs.length; i++) {
				      ipList += allNICs[i]+", ";
				    }
				    
				    Initiator.LOG_FILE.log(Level.CONFIG,"NIC Interfaces available:"+ipList);
				}
		
				// loop through each card and take the 1st valid dns entry that is returned
				for (int i=0;i<allNICs.length;i++) {
					
					try {
						byte[] thisIP = allNICs[i].getAddress();
						computerName = dns.getHostByAddr(thisIP).toUpperCase();
						Initiator.LOG_FILE.log(Level.INFO,"NIC Interface: "+allNICs[i]+ " passed and resolved as "+computerName);
						
						macAddress = MACAddressFinder.getMAC(allNICs[i]);
						ipAddress = allNICs[i].getHostAddress();
							
						Initiator.LOG_FILE.log(Level.INFO,"MAC address discovered as: "+allNICs[i]);
						
						break;
					}
					catch (UnknownHostException ex) {
						Initiator.LOG_FILE.log(Level.CONFIG,"Tried DNS Lookup on "+allNICs[i]+" and failed.");
						computerName = null;
					}
				}
			}
		}
		catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			Initiator.LOG_FILE.log(Level.ALL,e.toString());
		}
	}
	
	public String getOperatingSystem() {
		return operatingSystem;
	}
	
	/**
	 * 
	 * @return The serial number of this computer
	 */
	public String getSerialNumber() {
		return serialNumber;
	}
	
	/**
	 * @return The domain that the user is logged into
	 */
	public String getDomain() {
		return domainName;
	}
	
	/** 
	 * @return The BUILD envvar on this system
	 */
	public String getOsBuild() {
		return osBuild;
	}
	
	/**
	 * @return The computer name for this client
	 */
	public String getComputerName() {
		return computerName;
	}
	
	/**
	 * @return The version of this runtime jar that is running
	 */
	public String getPawsVersion() {
		return pawsVersion;
	}
	
	public String getMacAddress() {
		return macAddress;
	}
	
	public String getIpAddress() {
		return ipAddress;
	}
}
